package com.et.generator.impl.adapter;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;

/**
 * <p>数据库表生成对应的模型</p>
 * @author defier Lai
 * <p>Date: 2009-12-6 下午11:59:32</p>
 * @version 1.0
 */
public abstract class Executor {
	
	private List<String> tables;
	private Class<?> domainBaseClass;
	private String packageName;
	private Connection conn;

	/**
	 * 不同的数据库类型字段类型于获取表信息略有差别
	 * @param conn
	 * @throws SQLException 
	 * @throws FileNotFoundException 
	 */
	public void run() throws Exception {
		if(tables == null || tables.size() <= 0 || packageName == null || packageName.trim().equals("") || domainBaseClass == null || conn == null) {
			throw new IllegalArgumentException("参数错误或者参数不全");
		}
		for(String tableName : tables) {
			String className = "";
			String[] names = tableName.split("_");
			
			for(String name : names) {
				className += String.valueOf(name.charAt(0)).toUpperCase() + name.substring(1);
			}

			StringBuilder head = new StringBuilder();
			StringBuilder title = new StringBuilder();
			
			head.append("package " + packageName + ";\r\n");
			head.append("import " + domainBaseClass.getName() +";" + "\r\n"
					 	+ "import com.et.ar.annotations.Column;" + "\r\n"
					 	+ "import com.et.ar.annotations.Id;" + "\r\n"
					 	+ "import com.et.ar.annotations.Table;" + "\r\n");
			title.append("/**" + "\r\n" 
					+ " * <p>" + tableName + "</p>" + "\r\n"
					+ " * @author et2mvc" + "\r\n" 
					+ " * @version 1.0" + "\r\n"
					+ " */" + "\r\n");
			
			title.append("@Table(name=\"" + tableName + "\")\r\n");
			title.append("public class " + className
						+ " extends "+ domainBaseClass.getSimpleName() +" {" + "\r\n\r\n");
			
			StringBuilder body = new StringBuilder();
			String sql = "select * from " +tableName;
			
			boolean timestampType = false;
			boolean timeType = false;
			boolean dateType = false;

			ResultSet rs = conn.createStatement().executeQuery(sql);
			ResultSetMetaData rsmd = rs.getMetaData();
			
			for (int i = 1; i <= rsmd.getColumnCount(); i++) {
				String s = rsmd.getColumnTypeName(i);
				String type = s;
				if (s.indexOf(" ") != -1) {// 防止取出的类似type====INTEGER
					type = s.substring(0, s.indexOf(" "));
				}

				// 取出表中的主键名字
				String sid = "Column";
				String name = rsmd.getColumnName(i).toLowerCase();
				ResultSet pkRSet = conn.getMetaData().getPrimaryKeys(null, null, tableName.toUpperCase());
				while (pkRSet.next()) {
					String keyName = pkRSet.getObject("COLUMN_NAME").toString();
					if (keyName.equalsIgnoreCase(name)) {
						sid = "Id";
					} else {
						sid = "Column";
					}
				}

				type = getColumnType(type);
				
				String outs = "    @" + sid + " \r\n	private " + type + " " + name + ";\r\n";
				title.append(outs);

				String name2 = String.valueOf(name.charAt(0)).toUpperCase()
								+ name.substring(1).toLowerCase();
				String set = "    public void set" + name2 + "(" + type
							+ " " + name + ") {\r\n" 
							+ "        this." + name
							+ " = " + name + ";\r\n" 
							+ "    }\r\n";
				String get = "    public " + type + " get" + name2
							+ "(){\r\n" + "        return " + name + ";\r\n"
							+ "    }\r\n";
				body.append(get);
				body.append(set);
				
				if (type.equalsIgnoreCase("Timestamp")) {
					timestampType = true;
				} else if (type.equalsIgnoreCase("Time")) {
					timeType = true;
				} else if (type.equalsIgnoreCase("Date")) {
					dateType = true;
				}
			}
			rs.close();
			if (timestampType) {
				head.append("import java.sql.Timestamp;" + "\r\n");
			}
			if (timeType) {
				head.append("import java.sql.Time;" + "\r\n");
			}
			if (dateType) {
				head.append("import java.sql.Date;" + "\r\n");
			}

			StringBuilder classSb = new StringBuilder();
			classSb.append(head);
			classSb.append(title+"\r\n");
			classSb.append(body);
			classSb.append("}");
			
			File path = new File(System.getProperty("user.dir") + "/src/" + packageName.replace('.', '/'));
			if (!path.exists()) {
				path.mkdirs();
			}
			File file = new File(path + "/" + className + ".java");
			if(!file.exists() && file.createNewFile()) {
				OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(file),Charset.forName("utf-8"));
				os.write(classSb.toString());
				os.flush();
				os.close();
				System.out.println(tableName+"对应 model 生成成功...");
			} else {
				System.err.println(tableName+"对应 model 已经存在，执行失败...");
			}
		}
		System.out.println("所有model生成完成...");
	}

	public void setTableNames(List<String> tables) {
		this.tables = tables;
	}
	
	public void setDomainBaseClass (Class<?> domainBaseClass) {
		this.domainBaseClass = domainBaseClass;
	}
	
	public void setPackageName(String packageName) {
		this.packageName = packageName;
	}
	
	public void setConnection(Connection conn) {
		this.conn = conn;
	}
	
	/**
	 * 从数据库中获取所有数据表
	 * @param conn
	 * @return
	 * @throws SQLException
	 */
	protected abstract List<String> getTables(Connection conn) throws SQLException;
	
	/**
	 * 分析数据表列类型
	 * @param type
	 * @return
	 */
	protected abstract String getColumnType(String type);
	
}
